﻿using System.Data.Common;
using System.Configuration;
using System.Collections.Generic;
using Microsoft.Practices.EnterpriseLibrary.Data;

namespace Coderuse.CoreLib.DataAccess
{
    public static class DatabaseFactory
    {
        // Dictionary used to cache the Database objects.
        private static Dictionary<string, Database> _databases = new Dictionary<string, Database>();

        // Lock object used to add new Database object into _databases,
        // this is for thread safe.
        private static object _lockObject = new object();

        /// <summary>
        /// Creates a <see cref="Database"/> object, this Database object is used to
        /// execute database operation. For the performance reason, this 
        /// Database object is cached in the DMinSite.Server.DataAccess.DatabaseFactory class according
        /// to parameter <paramref name="name"/> as the key. 
        /// </summary>
        /// <param name="name">The key for caching.</param>
        /// <returns>A <c>Database</c> instance.</returns>
        public static Database CreateDatabase()
        {
            string connectionString = null;
            string providerName = null;
            Database database = null;
            // If the _databases does not has the database, or the contained
            // database object is null, try to create a new database, and add
            // it to _databases.
            if (_databases.TryGetValue("ConnectionString", out database))
            {
                if (null != database)
                {
                    return database;
                }
            }

            lock (_lockObject)
            {
                connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                providerName = ConfigurationManager.ConnectionStrings["ConnectionString"].ProviderName;

                if (string.IsNullOrEmpty(connectionString))
                {
                    throw new ConfigurationErrorsException("Cannot find connection string of ConnectionString.");
                }

                connectionString = CryptoUtils.CryptoUtils.DecryptWithEmbeddedKeyPhrase(connectionString);

                database = new GenericDatabase(connectionString, DbProviderFactories.GetFactory(providerName));
                _databases.Add("ConnectionString", database);
            }

            return database;
        }
    }
}
